package com.nny.alarm.widget;

import java.text.DateFormatSymbols;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import com.uxwine.alarm.Alarm;
import com.uxwine.alarm.TimeCycle2;
import com.uxwine.alarm.TimeRecord;
import com.nny.alarm.R;
import com.uxwine.util.Lunar;
import com.uxwine.util.UxToast;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

public class TimeView extends LinearLayout
{
	
	Map<Integer, DigitalView> mDViews;
	TextView mtvTipView;
	Alarm mAlarm;
	String[] mWeekDays;
	DateFormatSymbols mDateFmt;
	int mnCurrent = TimeRecord.YEAR;
	int mnFirst = TimeRecord.YEAR;
	private Bitmap[] mSelectBitmaps;
	private Bitmap[] mNormalBitmaps;
	OnDigitalClickedListener mOnDigitalClickedListener;
	
	public TimeView(Context context, AttributeSet attrs)
	{
		super(context, attrs);
		initView();
	}	
	
	public void initView()
	{
		View.inflate(getContext(), R.layout.view_digital_time, this);
		setOrientation(LinearLayout.HORIZONTAL);
		
		mtvTipView = (TextView)findViewById(R.id.digital_time_tip);
		
		mSelectBitmaps = loadBitmaps(10, "digital_selected_");		
		mNormalBitmaps = loadBitmaps(10, "digital_normal_");
		
		mDViews = new HashMap<Integer, DigitalView>();
		
		mDateFmt = new DateFormatSymbols();
		mWeekDays = mDateFmt.getWeekdays();
		
		setupDigitals(mNormalBitmaps, mSelectBitmaps, mNormalBitmaps);
	}
	
	public void setOnDigitalClickedListener(OnDigitalClickedListener l)
	{
		mOnDigitalClickedListener = l;
	}
	
	private void setupDigitals(final Bitmap[] n, final Bitmap[] s, final Bitmap[] d)
	{
		DigitalView dv = (DigitalView)findViewById(R.id.digital_time_year);
		mDViews.put(TimeRecord.YEAR, dv);
		dv.setOnClickListener(new MOnClickListener(TimeRecord.YEAR));
		dv.setBitmaps(n, s, d);
		
		dv = (DigitalView)findViewById(R.id.digital_time_month);
		mDViews.put(TimeRecord.MONTH, dv);
		dv.setOnClickListener(new MOnClickListener(TimeRecord.MONTH));
		dv.setBitmaps(n, s, d);
		
		dv = (DigitalView)findViewById(R.id.digital_time_date);
		mDViews.put(TimeRecord.DATE, dv);
		dv.setOnClickListener(new MOnClickListener(TimeRecord.DATE));
		dv.setBitmaps(n, s, d);
		
		dv = (DigitalView)findViewById(R.id.digital_time_hour);
		mDViews.put(TimeRecord.HOUR, dv);
		dv.setOnClickListener(new MOnClickListener(TimeRecord.HOUR));
		dv.setBitmaps(n, s, d);
		
		dv = (DigitalView)findViewById(R.id.digital_time_minute);
		mDViews.put(TimeRecord.MINUTE, dv);
		dv.setOnClickListener(new MOnClickListener(TimeRecord.MINUTE));
		dv.setBitmaps(n, s, d);
	}
	
	public void update(Alarm alarm)
	{
		mAlarm = alarm;
		final TimeRecord t = alarm.time;
		final TimeCycle2 tc = alarm.cycle;
		Calendar c = Calendar.getInstance();
		c.setTimeInMillis(System.currentTimeMillis());
		
		reset();
		switch(tc.getCycle())
		{
		case TimeCycle2.TYPE_ONCE:updateOnce(t, tc, c);break;
		case TimeCycle2.TYPE_YEAR:updateYear(t, tc, c);break;
		case TimeCycle2.TYPE_MONTH:updateMonth(t, tc, c);break;
		default:updateDay(t, tc, c);break;
		}		
		setEnables(alarm.cycle);
	}
	
	public void reset()
	{
		mnCurrent = -1;
		mnFirst = TimeRecord.YEAR;
		updateDigitals();
	}
	
	public void updateOnce(TimeRecord t, TimeCycle2 tc, Calendar c)
	{
		final Context ctx = getContext();
		mnFirst = TimeRecord.YEAR;
		mnCurrent = TimeRecord.YEAR;
		initDigitals(t, c, mnFirst);
		
		setTipView(ctx, c);
	}
	
	public void updateYear(TimeRecord t, TimeCycle2 tc, Calendar c)
	{
		mnFirst = TimeRecord.MONTH;
		mnCurrent = TimeRecord.MONTH;
		initDigitals(t, c, mnFirst);
		mtvTipView.setText("");
	}
	
	public void updateMonth(TimeRecord t, TimeCycle2 tc, Calendar c)
	{
		mnFirst = TimeRecord.DATE;
		mnCurrent = TimeRecord.DATE;
		initDigitals(t, c, mnFirst);
		mtvTipView.setText("");
	}
	
	public void updateDay(TimeRecord t, TimeCycle2 tc, Calendar c)
	{
		mnFirst = TimeRecord.HOUR;
		mnCurrent = TimeRecord.HOUR;

		initDigitals(t, c, mnFirst);
		mtvTipView.setText("");
	}
	
//	public void setCycleMask(int mask)
//	{
//		if(null == mAlarm)
//			return;
//		mAlarm.cycle.set(mask);
//	}
	
	public void set(int key, int value)
	{
		if(mAlarm == null)
			return;
		mAlarm.time.set(key, value);
		setText(key, key == TimeRecord.MONTH ? value + 1: value);
		
		if(mAlarm.cycle.getCycle() == TimeCycle2.TYPE_ONCE)
		{
			setTipView();
		}
	}
	
	protected void setTipView()
	{
		final TimeRecord tr = mAlarm.time;
		final Context ctx = getContext();
		Calendar c = Calendar.getInstance();
		c.set(tr.get(TimeRecord.YEAR), 
				tr.get(TimeRecord.MONTH), 
				tr.get(TimeRecord.DATE));
		
		setTipView(ctx, c);
	}
	
	protected void setTipView(Context ctx, Calendar c)
	{
		Locale locale = Locale.getDefault();

		if(locale.getCountry().contains("CN"))
		{
			Lunar l = new Lunar(c);
			mtvTipView.setText(ctx.getString(
					R.string.digital_time_tip_lu,
					l.getMonth(), 
					l.getDay(), 
					mWeekDays[c.get(Calendar.DAY_OF_WEEK)]));
		}
		else
		{
			mtvTipView.setText(mWeekDays[c.get(Calendar.DAY_OF_WEEK)]);			
		}
	}
	
	public void setText(int key, int value)
	{
		DigitalView dv = mDViews.get(key);
		dv.setValue(value);
		dv.updateView();
	}
	
	public void setEnables(TimeCycle2 cycle)
	{
		
	}
	
	public void initDigitals(TimeRecord t, Calendar c, int first)
	{		
		Set<Map.Entry<Integer, DigitalView>> set = mDViews.entrySet();
        for (Iterator<Map.Entry<Integer, DigitalView>> it = set.iterator(); it.hasNext();)
        {
            Map.Entry<Integer, DigitalView> entry = (Map.Entry<Integer, DigitalView>) it.next();
            
            final int key = entry.getKey();
            final DigitalView dv = entry.getValue();
            int value = first <= key ? t.get(key) : c.get(getCalenderKey(key));
            if(key == TimeRecord.MONTH)
            {
            	value += 1;
            }
            dv.setValue(value);
            dv.setEnabled(first <= key);
    		dv.setShowMarker(mnCurrent == key);
            dv.updateView();            
        }
	}
	
	public void updateDigitals()
	{		
		Set<Map.Entry<Integer, DigitalView>> set = mDViews.entrySet();
        for (Iterator<Map.Entry<Integer, DigitalView>> it = set.iterator(); it.hasNext();)
        {
            Map.Entry<Integer, DigitalView> entry = (Map.Entry<Integer, DigitalView>) it.next();
            
            final int key = entry.getKey();
            final DigitalView dv = entry.getValue();
    		dv.setShowMarker(mnCurrent == key);
    		dv.setSelected(mnFirst <= key && key <= mnCurrent);
            dv.updateView();            
        }
	}
	
	public int getCalenderKey(int key)
	{
		switch(key)
		{
		case TimeRecord.YEAR:
			return Calendar.YEAR;
		case TimeRecord.MONTH:
			return Calendar.MONTH;
		case TimeRecord.DATE:
			return Calendar.DAY_OF_MONTH;
		case TimeRecord.HOUR:
			return Calendar.HOUR_OF_DAY;
		case TimeRecord.MINUTE:
			return Calendar.MINUTE;
		case TimeRecord.SECOND:
			return Calendar.SECOND;
		default:
			throw new IllegalArgumentException();
		}
	}
	
	public int next()
	{
		if(mnCurrent == TimeRecord.YEAR)
		{
			mnCurrent = TimeRecord.MONTH;
		}
		else if(mnCurrent == TimeRecord.MONTH)
		{
			mnCurrent = TimeRecord.DATE;
		}
		else if(mnCurrent == TimeRecord.DATE)
		{
			mnCurrent = TimeRecord.HOUR;
		}
		else if(mnCurrent == TimeRecord.HOUR)
		{
			mnCurrent = TimeRecord.MINUTE;
		}		
		else if(mnCurrent == TimeRecord.MINUTE)
		{
			mnCurrent = TimeRecord.SECOND;
		}
		else
		{
			throw new IllegalArgumentException();
		}
		updateDigitals();
		return mnCurrent;
	}
	
	public void setStep(int step)
	{
		if(step < TimeRecord.YEAR || step > TimeRecord.SECOND)
			throw new IllegalArgumentException();
			
		mnCurrent = step;
		updateDigitals();
	}
	
	public int first()
	{
		return mnFirst;
	}
	
	public int current()
	{
		return mnCurrent;
	}
	
	private Bitmap[] loadBitmaps(int count, String prefix)
	{
		final Context context = getContext();
		final Resources r = context.getResources();
		final String pkgName = context.getPackageName();
		Bitmap[] bms = new Bitmap[count];
		for(int i = 0; i < count; i++)
		{
			int id = r.getIdentifier(prefix + i, "drawable", pkgName);
			bms[i] = BitmapFactory.decodeResource(r, id);
		}
		return bms;
	}
	
	public interface OnDigitalClickedListener
	{
		public void onDigitalClicked(DigitalView dv, int type);
	}
	
	class MOnClickListener implements View.OnClickListener
	{
		int mnType;
		public MOnClickListener(int type)
		{
			mnType = type;
		}
		
		@Override
		public void onClick(View v)
		{
			if(null != mOnDigitalClickedListener && v instanceof DigitalView)
			{
				mOnDigitalClickedListener.onDigitalClicked((DigitalView)v, mnType);
			}
		}		
	}
}
